package com.zxy.ziems.server.device.modules.impl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.baomidou.mybatisplus.core.toolkit.reflect.SpringReflectionHelper;
import com.zxy.btp.common.util.JsonUtils;
import com.zxy.ziems.server.device.modules.DevicePropertyProcessor;
import com.zxy.ziems.server.device.pojo.bo.Triplet;
import com.zxy.ziems.server.utils.AssertUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.function.BiConsumer;

/**
 * 属性高级配置
 * @author 10348359
 * @create 2024-04-28 10:10
 */
@Slf4j
@Service
public class DevicePropertyProcessorManager implements ApplicationListener<ApplicationReadyEvent> {

    public <R> void doProcessDecodeAdvancedConfigIfPresentBy(String protocolType, String advanced, BiConsumer<? super DevicePropertyProcessor, R> action) {
        if (Objects.isNull(action)) {
            return;
        }

        if (Objects.isNull(protocolType)) {
            return;
        }

        if (StrUtil.isBlank(advanced)) {
            return;
        }
        String newKey = protocolType;
        Triplet<Class<?>, Class<?>, DevicePropertyProcessor> pair = processorMap.get(newKey);
        if (Objects.isNull(pair)) {
            return;
        }
        R config = (R) JsonUtils.parseObject(advanced, pair.getSecond());

        action.accept(pair.getThird(), config);
    }

    public <T> void doProcessAdvancedConfigIfPresentBy(String protocolType, Object advanced, BiConsumer<? super DevicePropertyProcessor, T> action) {
        if (Objects.isNull(advanced)) {
            return;
        }

        if (Objects.isNull(action)) {
            return;
        }

        if (Objects.isNull(protocolType)) {
            return;
        }

        String newKey = protocolType;;
        Triplet<Class<?>, Class<?>, DevicePropertyProcessor> pair = processorMap.get(newKey);
        if (Objects.isNull(pair)) {
            return;
        }

        T newExtra = (T) JsonUtils.parseObject(JsonUtils.toJSONString(advanced), pair.getFirst());
        AssertUtil.nonNull(newExtra, "extra:{}序列号失败", advanced);
        action.accept(pair.getThird(), newExtra);
    }

    private Map<String, Triplet<Class<?>, Class<?>, DevicePropertyProcessor>> processorMap = new HashMap<>(0);

    @Override
    public void onApplicationEvent(ApplicationReadyEvent event) {
        Map<String, DevicePropertyProcessor> beansOfType = SpringUtil.getBeansOfType(DevicePropertyProcessor.class);
        beansOfType.forEach((key, processor) -> {
            String protocolType = processor.supportProtocol();
            if (Objects.isNull(protocolType)) {
                return;
            }
            String newKey = protocolType;
            if (processorMap.containsKey(newKey)) {
                log.error("[通信通道]协议：{}重复处理", protocolType);
                return;
            }
            Class<?>[] typeArguments = SpringReflectionHelper.resolveTypeArguments(processor.getClass(), DevicePropertyProcessor.class);
            if (null == typeArguments || typeArguments.length < 2) {
                return;
            }
            Triplet<Class<?>, Class<?>, DevicePropertyProcessor> p = Triplet.of(typeArguments[0], typeArguments[1], processor);
            processorMap.put(newKey, p);
        });
    }
}
